package com.factory.code.lib.database;

import com.factory.code.controller.param.ConnectionParam;
import org.apache.commons.dbcp2.BasicDataSourceFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.SingleConnectionDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author tanghc
 */
public class DatabaseManager {

    private static final Logger logger = LoggerFactory.getLogger(DatabaseManager.class);


    private static final Map<String, DataSource> DATA_SOURCE_MAP = new ConcurrentHashMap<>(16);
    private static final ThreadLocal<Connection> CONNECTION_LOCAL = new ThreadLocal<>();

    public static Connection getConnection(ConnectionParam param) {
        Connection connection = CONNECTION_LOCAL.get();
        if (connection == null) {
            try {
                connection = getDataSource(param).getConnection();
                CONNECTION_LOCAL.set(connection);
            } catch (SQLException e) {
                logger.error("获取Connection失败, jdbcUrl:{}", param.getDbUrl(), e);
                throw new RuntimeException("获取Connection失败", e);
            }
        }
        return connection;
    }

    public static void closeConnection() {
        Connection connection = CONNECTION_LOCAL.get();
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        CONNECTION_LOCAL.remove();
    }

    private static final Map<String, JdbcTemplate> JDBC_TEMPLATE_MAP = new ConcurrentHashMap<>(16);

    public static JdbcTemplate getJdbcTemplate(ConnectionParam param) {
//        JdbcTemplate jdbcTemplate = JDBC_TEMPLATE_MAP.get(param.getDbUrl() + param.getDbUsername());
//        if (jdbcTemplate == null) {
        //会在1小时左右报错
            SingleConnectionDataSource dataSource = new SingleConnectionDataSource(param.getDbUrl(), param.getDbUsername(), param.getDbPassword(), false);
            dataSource.setDriverClassName(param.getDbDriver());
        JdbcTemplate      jdbcTemplate = new JdbcTemplate(dataSource);
//            jdbcTemplate = new JdbcTemplate(getDataSource(param));
            JDBC_TEMPLATE_MAP.put(param.getDbUrl() + param.getDbUsername(), jdbcTemplate);
//        }
        return jdbcTemplate;
    }

    public static DataSource getDataSource(ConnectionParam param) {
        String jdbcUrl = param.getDbUrl();
        DataSource dataSource = DATA_SOURCE_MAP.computeIfAbsent(jdbcUrl, key -> {
            Properties properties = new Properties();
            properties.put("driverClassName", param.getDbDriver());
            properties.put("url", param.getDbUrl());
            properties.put("username", param.getDbUsername());
            properties.put("password", param.getDbPassword());
            // 初始连接数
            properties.put("initialSize", 1);
            // 最大活跃数
            properties.put("maxTotal", 30);
            properties.put("minIdle", 5);
            properties.put("maxIdle", 10);
            // 最长等待时间(毫秒)
            properties.put("maxWaitMillis", 1000);
            // 程序中的连接不使用后是否被连接池回收
            properties.put("removeAbandonedOnMaintenance", true);
            properties.put("removeAbandonedOnBorrow", true);
            // 连接在所指定的秒数内未使用才会被删除(秒)
            properties.put("removeAbandonedTimeout", 5);
            try {
                return BasicDataSourceFactory.createDataSource(properties);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        });
        if (dataSource == null) {
            throw new RuntimeException("连接数据库失败");
        }
        return dataSource;
    }

}
